package com.sos.widget.view.groupTime;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import androidx.annotation.Nullable;

import com.sos.widget.log.LogUtils;

import java.util.ArrayList;
import java.util.List;

public class NumberFlipView extends View {

    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FAKE_BOLD_TEXT_FLAG);
    public int mFlipNumber = 0;
    public int maxNum = 0;
    private int mOutterFlipNumber = mFlipNumber;
    private Rect textRect = new Rect();
    private final float mMaxMoveHeight;
    private float mCurrentMoveHeight;
    private float mOutterMoveHeight;
    private float mCurrentAlphaValue;

    private List<String> flipNumbers = new ArrayList<>();
    private List<String> flipOutterNumbers = new ArrayList<>();

    public int getmFlipNumber() {
        return mFlipNumber;
    }

    public NumberFlipView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        paint.setColor(Color.parseColor("#333333"));

        int fontSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, context.getResources().getDisplayMetrics());
        paint.setTextSize(fontSize);

        mMaxMoveHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, context.getResources().getDisplayMetrics());
    }
    public NumberFlipView(Context context) {
        super(context);
        paint.setColor(Color.parseColor("#333333"));

        int fontSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 17, context.getResources().getDisplayMetrics());
        paint.setTextSize(fontSize);
        mMaxMoveHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, context.getResources().getDisplayMetrics());
    }

    public NumberFlipView(Context context,int color) {
        super(context);
        paint.setColor(color);

        int fontSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 17, context.getResources().getDisplayMetrics());
        paint.setTextSize(fontSize);
        mMaxMoveHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, context.getResources().getDisplayMetrics());
    }

    public NumberFlipView(Context context,int color,int textSize) {
        super(context);
        paint.setColor(color);

        int fontSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, textSize, context.getResources().getDisplayMetrics());
        paint.setTextSize(fontSize);
        mMaxMoveHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, context.getResources().getDisplayMetrics());
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        flipNumbers.clear();
        flipOutterNumbers.clear();


        String flipNumberString = toValue(mFlipNumber);
        for (int i = 0; i < flipNumberString.length(); i++) {
            flipNumbers.add(String.valueOf(flipNumberString.charAt(i)));
        }
        String flipOutterNumberString = toValue(mOutterFlipNumber);
        for (int i = 0; i < flipNumberString.length(); i++) {
                flipOutterNumbers.add(String.valueOf(flipOutterNumberString.charAt(i)));
        }

        paint.getTextBounds(toValue(mFlipNumber), 0, toValue(mFlipNumber).length(), textRect);
        final int textWidth = textRect.width();

        float curTextWidth = 0;
        for (int i = 0; i < flipNumbers.size(); i++) {

            paint.getTextBounds(flipNumbers.get(i), 0, flipNumbers.get(i).length(), textRect);
            final int numWidth = textRect.width();

            if (flipNumbers.get(i).equals(flipOutterNumbers.get(i))) {

                paint.setAlpha(255);
                canvas.drawText(flipNumbers.get(i), getWidth() / 2 - textWidth / 2 + curTextWidth, getHeight() / 2 + textRect.height() / 2, paint);
            } else {

                paint.setAlpha((int) (255 * (1 - mCurrentAlphaValue)));
                canvas.drawText(flipOutterNumbers.get(i), getWidth() / 2 - textWidth / 2 + curTextWidth, mOutterMoveHeight + getHeight() / 2 + textRect.height() / 2, paint);
                paint.setAlpha((int) (255 * mCurrentAlphaValue));
                canvas.drawText(flipNumbers.get(i), getWidth() / 2 - textWidth / 2 + curTextWidth, mCurrentMoveHeight + getHeight() / 2 + textRect.height() / 2, paint);
            }

            curTextWidth += (numWidth)+5;
        }
    }




    public String toValue(int value){
        if(value<10){
            return "0"+value;
        }
        return String.valueOf(value);
    }

    public void setNum(int maxNum) {
        this.maxNum = maxNum;
    }

    public void startTime(long count){
        this.mFlipNumber= (int) count;
        mOutterFlipNumber = mFlipNumber;
        if(mFlipNumber<0){
            mOutterFlipNumber=maxNum;
            mFlipNumber=maxNum;
        }
        ValueAnimator animator = ValueAnimator.ofFloat(mMaxMoveHeight, 0);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentMoveHeight = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator.setDuration(1000);
        animator.start();

        ValueAnimator animator1 = ValueAnimator.ofFloat(0, 1);
        animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentAlphaValue = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator1.setDuration(1000);
        animator1.start();

        ValueAnimator animator2 = ValueAnimator.ofFloat(0, -mMaxMoveHeight);
        animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mOutterMoveHeight = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator2.setDuration(1000);
        animator2.start();
    }


    public void jumpNumber() {
        mOutterFlipNumber = mFlipNumber;
        mFlipNumber-=1;
        if(mFlipNumber<0){
            mOutterFlipNumber=maxNum;
            mFlipNumber=maxNum;
        }
        ValueAnimator animator = ValueAnimator.ofFloat(mMaxMoveHeight, 0);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentMoveHeight = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator.setDuration(1000);
        animator.start();

        ValueAnimator animator1 = ValueAnimator.ofFloat(0, 1);
        animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentAlphaValue = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator1.setDuration(1000);
        animator1.start();

        ValueAnimator animator2 = ValueAnimator.ofFloat(0, -mMaxMoveHeight);
        animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mOutterMoveHeight = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator2.setDuration(1000);
        animator2.start();
    }

    /**
     * 比onDraw先执行
     * <p>
     * 一个MeasureSpec封装了父布局传递给子布局的布局要求，每个MeasureSpec代表了一组宽度和高度的要求。
     * 一个MeasureSpec由大小和模式组成
     * 它有三种模式：UNSPECIFIED(未指定),父元素部队自元素施加任何束缚，子元素可以得到任意想要的大小;
     * EXACTLY(完全)，父元素决定自元素的确切大小，子元素将被限定在给定的边界里而忽略它本身大小；
     * AT_MOST(至多)，子元素至多达到指定大小的值。
     * <p>
     * 它常用的三个函数：
     * 1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)
     * 2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
     * 3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        final int minimumWidth = getSuggestedMinimumWidth();
        final int minimumHeight = getSuggestedMinimumHeight();
        int width = measureWidth(minimumWidth, widthMeasureSpec);
        int height = measureHeight(minimumHeight, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int measureWidth(int defaultWidth, int measureSpec) {

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);


        switch (specMode) {
            case MeasureSpec.AT_MOST:
                defaultWidth = (int) paint.measureText("0 0") + getPaddingLeft() + getPaddingRight()+30;
                break;
            case MeasureSpec.EXACTLY:
                defaultWidth = specSize;
                break;
            case MeasureSpec.UNSPECIFIED:
                defaultWidth = Math.max(defaultWidth, specSize);
        }
        return defaultWidth;
    }


    private int measureHeight(int defaultHeight, int measureSpec) {

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        Log.e("YViewHeight", "---speSize = " + specSize + "");

        switch (specMode) {
            case MeasureSpec.AT_MOST:
                defaultHeight = (int) (-paint.ascent() + paint.descent()) + getPaddingTop() + getPaddingBottom();
                break;
            case MeasureSpec.EXACTLY:
                defaultHeight = specSize;
                break;
            case MeasureSpec.UNSPECIFIED:
                defaultHeight = Math.max(defaultHeight, specSize);
//        1.基准点是baseline
//        2.ascent：是baseline之上至字符最高处的距离
//        3.descent：是baseline之下至字符最低处的距离
//        4.leading：是上一行字符的descent到下一行的ascent之间的距离,也就是相邻行间的空白距离
//        5.top：是指的是最高字符到baseline的值,即ascent的最大值
//        6.bottom：是指最低字符到baseline的值,即descent的最大值

                break;
        }
        return defaultHeight;
    }
}
